﻿
namespace Patterns4Net.Tests.Core.CecilExtensions.CILPatternsMatching
{
    using Mono.Cecil.Cil;
    using NUnit.Framework;
    using Patterns4Net.Core.CecilExtensions.CILPatternsMatching;

    [TestFixture]
    public class CILPatternsMatcherTest
    {
        [Test]
        public void MatchesSimpleSequence()
        {
            var first = Instruction.Create(OpCodes.Ldc_I4_0);
            var instructions = new[]
                {
                    first, 
                    first, 
                    Instruction.Create(OpCodes.Ldc_I4_1), 
                    Instruction.Create(OpCodes.Ldc_I4_2),
                    null
                };
            var instrMatcher = new InstructionMatcherMock
                {
                    Instructions = instructions, 
                    CurrentIndex = 1
                };

            var matcher = new CILPatternsMatcher(instrMatcher);

            // this test is more about checking whether causes an inifinite loop, or an unexpected exception
            // rather then testing the result.
            var result = matcher.Matches(instructions[instrMatcher.CurrentIndex]);
            Assert.IsTrue(result);            
        }

        private class InstructionMatcherMock : InstructionMatcher
        {
            public Instruction[] Instructions { get; set; }

            public int CurrentIndex { get; set; }

            public override bool Found
            {
                get
                {
                    return this.Instructions != null && this.Instructions[this.CurrentIndex] == null;
                }

                protected set
                {
                }
            }

            public override bool Matches(Instruction instruction, out Instruction next)
            {
                next = this.Instructions[this.CurrentIndex++];
                return true;
            }

            public override void Reset()
            {
                this.Instructions = null;
            }
        }
    }
}
